/*
 * Copyright (c) 2020-2099 the original author or authors. All rights reserve.
 */
package org.tianyun.cloud.mybatis.plugins;

import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.tianyun.cloud.context.RequestContext;
import org.tianyun.cloud.context.RequestContext.RequestContextHolder;

import java.util.Map;

/**
 * 上下文请求参数插件
 *
 * @auther ebert_chan
 */
//@formatter:off
@Intercepts({
	@Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class }),
	@Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class }),
	@Signature(type = Executor.class, method = "queryCursor", args = { MappedStatement.class, Object.class, RowBounds.class }),
	@Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class})
})
//@formatter:on
public class RequestContextPlugin implements Interceptor {

    /*
     * @see org.apache.ibatis.plugin.Interceptor#intercept(org.apache.ibatis.plugin. Invocation)
     */
    @SuppressWarnings("unchecked")
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object[] args = invocation.getArgs();
        Object parameterObject = args[1];
        RequestContext context = RequestContextHolder.get();
        if (context != null) {

            ContextParamMap paramMap;
            if (parameterObject instanceof ContextParamMap) {
                paramMap = (ContextParamMap) parameterObject;
            } else {
                paramMap = new ContextParamMap();
                if (parameterObject != null) {
                    if (parameterObject instanceof Map) {
                        paramMap.putAll((Map<? extends String, ? extends Object>) parameterObject);
                    } else {
                        paramMap.put(ContextParamMap.DEFAULT_ARG_NAME, parameterObject);
                    }
                } else {
                    paramMap.put(ContextParamMap.DEFAULT_ARG_NAME, null);
                }
                args[1] = paramMap;
            }
            paramMap.put(ContextParamMap.DEFAULT_CONTEXT_NAME, context);

        }
        return invocation.proceed();
    }

}
